<template>
  <div class="wrap dashboard-editor-container">
    <div class="chat-list">
      <div>
        <div>
          <span class="list-button" @click="addChat">
            New chat
          </span>
        </div>
        <div :class="{'list-chatname':true, 'selected': item.isEdit}" v-for="item in historyList" :key="item.uuid" @click="chatClick(item.uuid)">
          <div class="list-name">
            <el-icon><ChatDotRound /></el-icon>
            <span v-show="!item.edit">{{item.title}}</span>
            <el-input ref="editInput" v-model="item.title" @keyup.enter.native="chatnameChange(item.uuid)"  @click.stop.native v-show="item.edit" size="mini" style="width:100px">{{item.title}}</el-input>
          </div>
          <div class="list-edit" v-show="item.isEdit">
            <i class="el-icon-edit" v-show="!item.edit" @click.stop="item.edit = true"></i>
            <el-popconfirm  title="确定删除此记录？"  @onConfirm="deleteChat(item.uuid)">
              <i class="el-icon-delete" slot="reference" v-show="!item.edit"></i>
            </el-popconfirm>
            <i class="el-icon-check" v-show="item.edit" @click.stop="item.edit = false"/>
          </div>
        </div>
      </div>
    </div> 
    <div class="chat-container">
      <!-- <el-header class="chat-header">
        <h2>Chat Room</h2>
      </el-header> -->
      <el-main class="chat-main">
        <div class="chat-messages" ref="chatMessages">
          <div v-for="(message, index) in messages" :key="index"  :class="{ 'chat-message-left': message.role === 'assistant', 'chat-message-right': message.role === 'user' }">
            <div class="chat-avatar">
              <img v-if="message.role === 'assistant'" src="../../assets/chatGPT.png" alt="">
            </div>
            <div class="chat-content">
              <span class="chat-time">{{ message.created }}</span>
              <!-- <span class="chat-message-text">{{ message.content }}</span> -->
              <span v-html="message.content" class="chat-message-text"></span>
              <!-- <pre><code>{{ message.content }}</code></pre> -->
            </div>
            <div class="chat-avatar">
              <img v-if="message.role === 'user'" src="https://raw.githubusercontent.com/Chanzhaoyu/chatgpt-web/main/src/assets/avatar.jpg" alt="">
            </div>
          </div>
          <div class="chat-message-left" v-show="loading">
            <div class="chat-avatar">
              <img src="../../assets/chatGPT.png" alt="">
            </div>
            <div class="chat-content">
              <span class="chat-message-text">思考中 <i class="el-icon-loading"></i></span>
            </div>
          </div>
        </div>
      </el-main>
      <el-footer class="chat-footer">
        <i class="el-icon-delete" @click="clearMessage"></i>
        <el-input v-model="inputText" placeholder="在这里输入你的信息..." class="chat-input" @keyup.enter.native="sendMessage"></el-input>
        <el-button type="primary" @click="sendMessage">发送</el-button>
      </el-footer>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
import { getuuid, parseTime } from '@/utils/index'
import { connrequest, downloadfile } from '@/api/firstPage'
import Hljs from "highlight.js";
import 'highlight.js/styles/vs.css'
// import 'highlight.js/styles/monokai-sublime.css'
// import "highlight.js/styles/github.css";
export default {
  data() {
    return {
      inputText: '',
      uuid:'',
      loading: false,
      edit: true,
      historyList:[],
      messages: [],
      apiMessage:[
        {role: 'system', content: 'you are a helpful assistant.'}
      ]
    };
  },
  //生命周期 - 创建完成（访问当前this实例）
  created() {
    // this.getModels()
    this.getData()
  },
  //生命周期 - 挂载完成（访问DOM元素）
  mounted() {
    if(!localStorage.getItem('binChatStorage')){
      let active = getuuid()
      let newchat = getuuid()
      let data = {
        active,
        chat: [
          {
            data: [],
            uuid: newchat
          }
        ],
        history: [
          {title: 'New chat', uuid: newchat, isEdit: true}
        ]
      }
      localStorage.setItem('binChatStorage', JSON.stringify(data))
    }
    this.$nextTick(() => {
      if(localStorage.getItem('binChatStorage')){
        let data = JSON.parse(localStorage.getItem('binChatStorage'))
        this.historyList = data.history
        if(this.historyList.length > 0){
          this.uuid = data.history.find(item => item.isEdit === true).uuid
          this.chatClick(this.uuid)
          this.$nextTick(() => {
            Hljs.highlightAll()
            this.$refs.chatMessages.scrollTop = this.$refs.chatMessages.scrollHeight;
          })
        }
      }
    })
  },
  methods: {
    async getData(){
      const data = {
        Data:{
          Name: "张三",
          Question: "xxx22",
          Answer: "yyyy333"
        },
        Action: 1
      }
      const res = await connrequest('GetChatGPTLog', data)
    },
    // async getModels(){
    //   const OPENAI_API_KEY = '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'
    //   const res = await axios.get('https://api.openai.com/v1/models',{
    //       headers: {
    //         'Content-Type': 'application/json',
    //         'Authorization': `Bearer ${OPENAI_API_KEY}` // 在环境变量中设置 OpenAI API 密钥
    //       }
    //     })
    //   console.log(res);
    // },
    addChat(){
      // 获取新聊天的 UUID 和本地存储数据
      let newchat = getuuid()
      let data = JSON.parse(localStorage.getItem('binChatStorage'))
      // 在 historyList 数组开头插入新聊天信息
      this.historyList.unshift( {title: 'New chat', uuid: newchat,  isEdit: true, edit: false} )
      // 更新本地存储数据中的 history 和 chat 数据
      data.history = this.historyList
      data.chat.unshift({data: [], uuid: newchat})
      localStorage.setItem('binChatStorage', JSON.stringify(data))
      this.chatClick(newchat)
    },
    chatClick(uuid){
      // 获取本地存储的数据
      let data = JSON.parse(localStorage.getItem('binChatStorage'))
       // 设置当前聊天 UUID，并更新 historyList 以指示哪个聊天是活动状态
      this.uuid = uuid
      this.historyList.forEach(item => item.isEdit = item.uuid === this.uuid);
      // 查找所选聊天的聊天消息
      let item = data.chat.find(item => item.uuid === this.uuid)
      let arr = Array.isArray(item.data) ? item.data : [{...item.data}]
      // 更新消息数组和 API 消息数组
      this.messages = arr
      this.apiMessage = [...arr]
      // 更新本地存储并将聊天窗口滚动到底部
      this.$nextTick(() => {
        localStorage.setItem('binChatStorage', JSON.stringify({...data, history: this.historyList}))
        this.$refs.chatMessages.scrollTop = this.$refs.chatMessages.scrollHeight;
      })
    },
    deleteChat(uuid){
      let data = JSON.parse(localStorage.getItem('binChatStorage'))
      this.historyList = this.historyList.filter(item => item.uuid !== uuid)
      data.chat = data.chat.filter(item => item.uuid !== uuid)
      data.history = this.historyList
      if(this.historyList.length > 0){
        this.chatClick(this.historyList[0].uuid)
      }else{
        this.messages = []
      }
      localStorage.setItem('binChatStorage', JSON.stringify(data))
    },
    chatnameChange(uuid){
      let data = JSON.parse(localStorage.getItem('binChatStorage'))
      data.history = this.historyList.map(item => {
        if(item.uuid === uuid){
          item.edit = false
        }
        return item
      })
      localStorage.setItem('binChatStorage', JSON.stringify(data))
    },
    async generateText(prompt) {
      const API_ENDPOINT = 'https://api.openai.com/v1/chat/completions';
      const OPENAI_API_KEY = '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'
      try {
        this.apiMessage.push({role:'user', content: prompt})
        this.apiMessage = this.apiMessage.map(item => {
          delete item.created
          return item
        })
        const response = await axios.post(API_ENDPOINT, {
          model: 'gpt-3.5-turbo-0301',
          // model: 'gpt-4',
          messages:this.apiMessage,
          temperature: 0.7, // 采样温度：介于0和2之间。较高的值（如0.8）会使输出更随机，而较低的值（如0.2）则会使其更加集中和确定性
          max_tokens: 1024
        }, {
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${OPENAI_API_KEY}` // 在环境变量中设置 OpenAI API 密钥
          }
        });
        return response.data;
      } catch (error) {
        this.loading = false
        this.messages.push({content: `发生错误：${error.message}`, role: 'assistant', created: parseTime(Date.parse(new Date())) });
      }
    },
    async sendMessage() {
      this.loading = true
      // 将用户输入的文本添加到消息列表中，并清空输入框
      const userMessage = { content: this.inputText, role: 'user', created: parseTime(Date.parse(new Date())) };
      this.messages.push(userMessage);
      this.inputText = '';
      // 发送信息后返回div底部
      this.$nextTick(() => {
        this.$refs.chatMessages.scrollTop = this.$refs.chatMessages.scrollHeight;
      })
      // 如果没有历史聊天记录，则创建新的聊天记录
      if(this.historyList.length === 0){
        let newchat = getuuid()
        let data = JSON.parse(localStorage.getItem('binChatStorage'))
        this.historyList.unshift( {title: 'New chat', uuid: newchat,  isEdit: true, edit: false} )
        data.history = this.historyList
        data.chat.unshift({data: userMessage, uuid: newchat})
        localStorage.setItem('binChatStorage', JSON.stringify(data))
        this.chatClick(newchat)
      }
      // 向后端发送请求，获取机器人的回复
      const res = await this.generateText(userMessage.content)
      if(res){
        this.loading = false
        // 获取本地存储的数据
        let data = JSON.parse(localStorage.getItem('binChatStorage'))
        // 根据 uuid 查找聊天记录列表中的当前聊天记录
        let item = data.chat.find(item => item.uuid === this.uuid)
        // 匹配 HTML 标签的正则表达式
        const htmlRegex = /<|>/g;
        // 匹配代码块的正则表达式
        const codeRegex = /```(\S+)?\n([\s\S]+?)```/g;
        // 对返回结果进行处理，将 HTML 标签和代码块转换为对应的格式
        const output = res.choices[0].message.content
          .replace(htmlRegex, match => (match === '<' ? '&lt;' : '&gt;'))
          .replace(codeRegex, '<pre><code class="$1">$2</code></pre>');
        // 构建机器人消息对象
        const botMessage = {
          role:res.choices[0].message.role,
          content: output,
          created: parseTime(res.created)
        };
        // 将机器人消息添加到聊天记录中
        this.messages.push(botMessage);
        // 添加机器人消息到 API 发送的消息列表中
        this.apiMessage.push(res.choices[0].message)
        // 更新当前聊天记录的数据
        item.data = this.messages
        // 将更新后的数据重新存储到本地
        localStorage.setItem('binChatStorage', JSON.stringify(data))
      }
      // 接收回复后返回div底部
      this.$nextTick(() => {
        Hljs.highlightAll()
        this.$refs.chatMessages.scrollTop = this.$refs.chatMessages.scrollHeight;
      })
    },
    clearMessage(){
      this.$confirm('是否清空会话?', '清空会话', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.messages = []
        this.apiMessage = [{role: 'system', content: 'you are a helpful assistant.'}]
        this.$message({
          type: 'success',
          message: '会话已清空!'
        });
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消'
        });          
      });
    },
    // 定义逐字显示方法
    printSlowly(text) {
      let i = 0;
      const timer = setInterval(() => {
        if (i < text.length) {
          i++;
        } else {
          clearInterval(timer);
        }
      }, 1000); // 设置每隔1秒钟输出一个字符
      return '';
    }
  }
};
</script>
<style scoped lang="scss">
/* @import url(); 引入css类 */
.wrap{
  display: flex;
  height: calc(100vh - 65px);
}
.chat-list{
  width: 260px;
  height: 100%;
  background: #fff;
  margin-right: 10px;
  padding: 10px;
  overflow-y: auto;
  .list-button{
    cursor: pointer;
    display: block;
    padding: 10px;
    margin-bottom: 15px;
    border: 1px dashed #ddd;
    text-align: center;
  }
  .list-chatname{
    display: flex;
    justify-content: space-between;
    font-size: 14px;
    padding: 10px;
    margin-bottom: 10px;
    border: 1px solid #ddd;
    cursor: pointer;
    border-radius: 8px;
    i{
      margin-right: 5px;
    }
    &:hover{
      color: #5ca66e;
      border: 1px solid #5ca66e;
      background: #f5f5f5;
    }
  }
  .selected{
    color: #5ca66e;
    border: 1px solid #5ca66e;
    background: #f5f5f5;
  }
  .list-edit{
    display: flex;
    align-items: center;
  }
}
.chat-container {
  width: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
}

.chat-header {
  background-color: #409eff;
  color: white;
  text-align: center;
}

.chat-main {
  flex: 1;
  padding: 20px;
  padding-bottom: 120px;
  background: #ffffff;
}

.chat-messages {
  height: calc(100vh - 220px);
  overflow-y: auto;
  font-size: 14px;
  line-height: 25px;
  display: flex;
  flex-direction: column;
}
.chat-avatar{
  padding-top: 10px;
  img{
    width: 35px;
    border-radius: 50%;
  }
}
.chat-content{
  display: flex;
  flex-direction: column;
}
pre{
  width: 50vw;
  // background-color: #f4f6f8;
  padding: 10px;
  border-radius: 10px;
}
code{
  width: 100%;
}
.chat-message-left {
  display: flex;
  max-width: 80%;
  border-radius: 5px;
  margin: 10px 0;
  align-self: flex-start;
  .chat-message-text{
    align-self: flex-start;
    margin-left: 10px;
    border-radius: 5px;
    padding: 10px;
    background-color: #f4f6f8;
  }
  .chat-time{
    align-self: flex-start;
    font-size: 12px;
    color: #ccc;
    padding-left: 10px;
  }
}

.chat-message-right {
  display: flex;
  max-width: 80%;
  border-radius: 5px;
  margin: 10px 0;
  align-self: flex-end;
  .chat-message-text{
    align-self: flex-end;
    margin-right: 10px;
    border-radius: 5px;
    padding: 10px;
    background-color: #d3f9d2;
  }
  .chat-time{
    font-size: 12px;
    color: #ccc;
    padding-right: 10px;
    align-self: flex-end;
  }
}


.chat-input {
  flex: 1;
  margin-right: 10px;
}

.chat-footer {
  position: absolute;
  bottom: 10px;
  width: 80%;
  left: 10%;
  display: flex;
  align-items: center;
  padding: 10px;
  .el-icon-delete{
    font-size: 18px;
    margin-right: 10px;
  }
}

</style>